package org.blogspot.t0yv0.marcalog.controller

import com.google.appengine.api.blobstore._
import org.blogspot.t0yv0.marcalog.model._
import org.blogspot.t0yv0.marcalog.util._
import org.blogspot.t0yv0.marcalog.view._

sealed class Controller(ctx: HttpContext, pm: DataManager) 
extends TemplateEngine {

  private val letters = '_'.toInt :: List.range('a','{');
  variables.put("letters", letters.map(_.toChar).toArray);

  def dec(x: String) =
    java.net.URLDecoder.decode(x, "UTF-8")

  def content = {
    ctx.response.setHeader("cache-control", "public, max-age=600");
  }

  def dispatch {
    val uri   = ctx.request.getRequestURI();
    val parts = uri.split('/').filter(_.length > 0);
    parts match {
      case Array()                     => index;
      case Array("item", n)            => item(dec(n));
      case Array("person", n)          => person(dec(n));
      case Array("items", k)           => items(dec(k).charAt(0));
      case Array("people", k)          => people(dec(k).charAt(0));
      case Array("admin", "upload")    => upload;
      case Array("admin", "uploading") => uploading;
      case Array("admin", "uploaded")  => uploaded;
      case Array("admin", "purge")     => purge;
      case Array("admin", "task", n)   => task(dec(n));
      case _                           => ctx.notFound;
    };
  }
    
  private def index {
    content;
    render("index");
  }

  private def item(id: String) {
    content;
    val i = pm.byId(classOf[Item], id);
    define("item", i);
    if (i.personId != "") {
      val p = pm.byId(classOf[Person], i.personId);
      define("person", p);
    }
    render("item");
  }

  private def person(id: String) {
    content;
    val p = pm.byId(classOf[Person], id);
    define("person", p);
    defItems("items", pm.find(classOf[Item], "personId", p.id));
    render("person");
  }

  private def items(c: Char) {
    content;
    defItems("items", pm.find(classOf[Item], "key", c.toInt));
    render("items");
  }

  private def people(c: Char) {
    content;
    defPeople("people", pm.find(classOf[Person], "key", c.toInt));
    render("people");
  }

  private def upload {
    content;
    define("action", blobstore.createUploadUrl("/admin/uploading"));
    render("upload");
  }

  private def uploading {
    val blob = blobstore.getUploadedBlobs(ctx.request).get("marc");
    Tasks.schedule(new ParseTask(blob));
    ctx.response.sendRedirect("/admin/uploaded");
  }

  private def uploaded {
    content;
    render("uploaded");
  }

  private def purge = {
    Tasks.schedule(new PurgeTask(classOf[Item].getName));
    Tasks.schedule(new PurgeTask(classOf[Person].getName));
    render("purge");
  }

  private def task(n: String) =
    Class.forName(n).newInstance.asInstanceOf[Task].execute(ctx, pm);

  private def define[T](key: String, value: T) =
    variables.put(key, value.asInstanceOf[Object]);
  
  private def defItems(key: String, value: Seq[Item]) =
    variables.put(key, value.toArray.sortBy(_.title))

  private def defPeople(key: String, value: Seq[Person]) =
    variables.put(key, value.toArray.sortBy(_.id))

  private def render(tpl: String) =
    template(tpl, ctx.response.getWriter);

  private val blobstore = 
    BlobstoreServiceFactory.getBlobstoreService();

}
